﻿<html DIR="LTR" xmlns:tool="http://www.microsoft.com/tooltip" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ddue="http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
  <head>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8" />
    <META NAME="save" CONTENT="history" />
    <title>了解 XA 事务</title>
    
    <link rel="stylesheet" type="text/css" href="../local/Classic.css">
      
    </link>
    
    <script src="../local/script.js">
      
    </script><script src="../local/script_main.js">&amp;nbsp;</script>
  </head>
  <body>
    <!--Topic built:04/01/2010 05:03:28-->

    
    
    
    
    
    
    
    
    
    <div id="header">
      <table width="100%" id="topTable"><tr>
          <td align="left">
            <span id="headerBold">了解 XA 事务</span>
          </td>
          <td align="right">
            
          </td>
        </tr></table>
      
      
      
    </div>
    <div id="mainSection">
      
        
        
    <font color="DarkGray">
      
    </font>
    <p />
    
    <p />
  
        <div id="introductionSection" class="section">
    <p>Microsoft SQL Server JDBC 提供程序提供对 Java Platform, Enterprise Edition/JDBC 2.0 可选分布式事务的支持。从 <a href="95fc7b07-2498-4a7e-8f7f-ee0d86b598b4.htm">SQLServerXADataSource</a> 类获取的 JDBC 连接可以参与标准分布式事务处理环境，例如 Java Platform, Enterprise Edition (Java EE) 应用程序服务器。</p>
    <p>用于此分布式事务实现的类如下：</p>
    <table width="100%" cellspacing="0" cellpadding="0" border="1" style="background-color: #CCCCCC;"><tr>
          <th>
            类
          </th>
          <th>
            实现
          </th>
          <th>
            说明
          </th>
        </tr><tr>
        <td>
          <p>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</p>
        </td>
        <td>
          <p>javax.sql.XADataSource</p>
        </td>
        <td>
          <p>分布式连接的类工厂。</p>
        </td>
      </tr><tr>
        <td>
          <p>com.microsoft.sqlserver.jdbc.SQLServerXAResource</p>
        </td>
        <td>
          <p>javax.transaction.xa.XAResource</p>
        </td>
        <td>
          <p>事务管理器的资源适配器。</p>
        </td>
      </tr></table>
    <div style="margin: .5em 1.5em .5em 1.5em"><b>注意：</b>
       XA 分布式事务连接默认使用“提交读”隔离级别。<p />
    </div>
  </div><h1 class="heading">使用 XA 事务的准则和限制</h1><div id="sectionSection0" class="section"><content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
      <p xmlns="">下面的列表提供了有关使用 XA 事务时的具体限制和准则的信息：</p>
      <ul xmlns=""><li>
          在 Windows XP 上：<br />
          当您通过 Microsoft SQL Server JDBC Driver 将 XA 事务用于 SQL Server 时，可能会注意到 XA 事务不起作用。仅当正参与 XA 事务的 SQL Server 正在 Windows XP 上运行时，才会出现此问题。另一方面，在 Windows XP 上运行且与不在 Windows XP 上运行的远程 SQL Server 相连的客户端应用程序可以参与 XA 事务。有关如何解决此问题的详细信息，请参阅 <a href="http://support.microsoft.com/kb/922668" target="_blank" alt=""><linkText xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">Windows XP COM+ 修复程序总成包 14 的可用性</linkText></a>中提供的修补程序。<br />
        </li><li>
          在 Windows Server 2003 上：<br />
          当您在 Windows Server 2003 上将 XA 事务与 Microsoft 分布式事务处理协调器 (MS DTC) 一起使用时，您可能会注意到 <b>XAResource.setTransactionTimeout</b> 方法不起作用。若要解决此问题，必须将 <a href="http://support.microsoft.com/kb/899756" target="_blank" alt=""><linkText xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">MSDTC 和 XA 事务</linkText></a>中提供的一个修补程序应用于正在参与 XA 事务的每一台 SQL Server 计算机。如果不应用此修补程序，则唯一有效的超时值为默认值 0，这意味着无限超时。<br />
        </li></ul>
      <p xmlns="">以下附加准则适用于紧密耦合的事务：</p>
      <ul xmlns=""><li>
          当您将 XA 事务与 Microsoft 分布式事务处理协调器 (MS DTC) 一起使用时，您可能会注意到 MS DTC 的当前版本不支持紧密结合的 XA 分支行为。例如，MS DTC 在 XA 分支事务 ID (XID) 与 MS DTC 事务 ID 之间具有一对一的映射，由松散耦合的 XA 分支执行的工作彼此之间是隔离的。<br />
          借助于在 <a href="http://support.microsoft.com/kb/938653" target="_blank" alt=""><linkText xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">MSDTC 和紧密结合的事务</linkText></a>中提供的修补程序，可以支持紧密结合的 XA 分支，其中，多个具有相同全局事务 ID (GTRID) 的 XA 分支映射到单一 MS DTC 事务 ID。这种支持使得多个紧密结合的 XA 分支可以在资源管理器（如 SQL Server）中看到彼此发生的变化。<br />
        </li><li>
          <a href="379857c3-9de1-4964-8782-32df317cbfbb.htm">SSTRANSTIGHTLYCPLD</a> 标志允许应用程序使用紧密结合的 XA 事务，这些事务具有不同的 XA 分支事务 ID (XID)，但具有相同的全局事务 ID (GTRID)。为了使用该功能，必须对 <b>XAResource.start</b> 方法的 <b>flags</b> 参数设置 <a href="379857c3-9de1-4964-8782-32df317cbfbb.htm">SSTRANSTIGHTLYCPLD</a>：<br />
          <div class="sampleCode"><span codeLanguage="other"><pre>xaRes.start(xid, SQLServerXAResource.SSTRANSTIGHTLYCPLD);</pre></span></div>
        </li></ul>
    </content></div><h1 class="heading">配置说明</h1><div id="sectionSection1" class="section"><content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
      <p xmlns="">如果要同时使用 XA 数据源和 Microsoft 分布式事务处理协调器 (MS DTC) 来处理分布式事务，则需要执行以下步骤。</p>
      <div style="margin: .5em 1.5em .5em 1.5em" xmlns=""><b>注意：</b>
        JDBC 分布式事务组件包含在 JDBC 驱动程序安装的 xa 目录中。这些组件包括 xa_install.sql 和 sqljdbc_xa.dll 文件。<p />
      </div>
    </content><sections xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
      <h1 class="heading" xmlns="">运行 MS DTC 服务</h1><div id="sectionSection" class="section" xmlns=""><content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <p xmlns="">在服务管理器中，MS DTC 服务应标记为“自动”，以确保其在启动 SQL Server 服务时运行。若要为 XA 事务启用 MS DTC，必须执行以下步骤：</p>
          <p xmlns="">在 Windows XP 和 Windows Server 2003 上：</p>
          <ol xmlns=""><li>
              在<b>“控制面板”</b>中，打开<b>“管理工具”</b>，然后打开<b>“组件服务”</b>。也可以单击<b>“开始”</b>按钮，单击<b>“运行”</b>，在<b>“打开”</b>框中键入 <b>dcomcnfg</b>，然后按<b>“确定”</b>打开<b>“组件服务”</b>。<br />
            </li><li>
              展开“组件服务”、“计算机”，右键单击<b>“我的电脑”</b>，然后选择<b>“属性”</b>。<br />
            </li><li>
              单击<b>“MSDTC”</b>选项卡，再单击<b>“安全性配置”</b>。<br />
            </li><li>
              选中“启用 XA 事务”复选框，然后单击“确定”。这将使 MS DTC 服务重新启动。<br />
            </li><li>
              再次单击“确定”以关闭“属性”对话框，然后关闭“组件服务”。<br />
            </li><li>
              停止 SQL Server，然后重新启动，以确保它与 MS DTC 更改同步。<br />
            </li></ol>
          <p xmlns="">在 Windows Vista 上：</p>
          <ol xmlns=""><li>
              单击<b>“开始”</b>按钮，在<b>“开始搜索”</b>框中键入 <b>dcomcnfg</b>，然后按 Enter 打开<b>“组件服务”</b>。也可以在<b>“开始搜索”</b>框中键入 %windir%\system32\comexp.msc 打开<b>“组件服务”</b>。<br />
            </li><li>
              依次展开“组件服务”、“计算机”、“我的电脑”和“分布式事务处理协调器”。<br />
            </li><li>
              右键单击<b>“本地 DTC”</b>，再选择<b>“属性”</b>。<br />
            </li><li>
              单击<b>“本地 DTC 属性”</b>对话框上的<b>“安全”</b>选项卡。<br />
            </li><li>
              选中<b>“启用 XA 事务”</b>复选框，然后单击<b>“确定”</b>。这将使 MS DTC 服务重新启动。<br />
            </li><li>
              再次单击<b>“确定”</b>以关闭<b>“属性”</b>对话框，然后关闭<b>“组件服务”</b>。<br />
            </li><li>
              停止 SQL Server，然后重新启动，确保它与 MS DTC 更改同步。<br />
            </li></ol>
        </content></div>
      <h1 class="heading" xmlns="">配置 JDBC 分布式事务组件</h1><div id="sectionSection" class="section" xmlns=""><content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <p xmlns="">可通过以下步骤配置 JDBC 驱动程序分布式事务组件：</p>
          <ol xmlns=""><li>
              将 sqljdbc_xa.dll 从 JDBC 安装目录复制到每台要参与分布式事务的 SQL Server 计算机的 Binn 目录中。<br />
              <div style="margin: .5em 1.5em .5em 1.5em"><b>注意：</b>
                 如果您将 XA 事务用于 32 位 SQL Server，则使用 x86 文件夹中的 sqljdbc_xa.dll 文件，即使 SQL Server 安装在 x64 处理器上也不例外。如果您在 x64 处理器上将 XA 事务用于 64 位 SQL Server，则使用 x64 文件夹中的 sqljdbc_xa.dll 文件。如果您是在 Itanium 处理器上将 XA 事务用于 64 位 SQL Server，则使用 IA64 文件夹中的 sqljdbc_xa.dll 文件。<p />
              </div>
            </li><li>
              对每个要参与分布式事务的 SQL Server 实例执行数据库脚本 xa_install.sql。此脚本将安装 sqljdbc_xa.dll 调用的扩展存储过程。这些扩展存储过程为 Microsoft SQL Server JDBC Driver 实现分布式事务和 XA 支持。需要以 SQL Server 实例管理员的身份来运行此脚本。<br />
            </li><li>
              若要为特定用户授予使用 JDBC Driver 参与分布式事务的权限，请将该用户添加至 SqlJDBCXAUser 角色。<br />
            </li></ol>
          <p xmlns="">在每个 SQL Server 实例上，一次只能配置一个版本的 sqljdbc_xa.dll 程序集。应用程序可能需要使用不同版本的 JDBC driver，才能使用 XA 连接来连接到同一个 SQL Server 实例。在这种情况下，必须在 SQL Server 实例上安装最新的 JDBC driver 附带的 sqljdbc_xa.dll。</p>
          <p xmlns="">可以通过三种方法来验证 SQL Server 实例上当前安装的 sqljdbc_xa.dll 的版本：</p>
          <ol xmlns=""><li>
              打开将参与分布式事务处理的 SQL Server 计算机的 LOG 目录。选择并打开 SQL Server 的“ERRORLOG”文件。在“ERRORLOG”文件中搜索“使用‘SQLJDBC_XA.dll’版本 ...”这一短语。<br />
            </li><li>
              打开将参与分布式事务处理的 SQL Server 计算机的 Binn 目录。选择 sqljdbc_xa.dll 程序集。<br />
              <ol><li>
                  在 Windows Vista 上：右键单击 sqljdbc_xa.dll，然后选择“属性”。然后单击<b>“详细信息”</b>选项卡。<b>“文件版本”</b>字段显示 SQL Server 实例上当前安装的 sqljdbc_xa.dll 的版本。<br />
                </li><li>
                  在 Windows XP 和 Windows 2003 Server 上：右键单击 sqljdbc_xa.dll，然后选择“属性”。接下来，单击<b>“版本”</b>选项卡。<b>“文件版本”</b>字段显示 SQL Server 实例上当前安装的 sqljdbc_xa.dll 的版本。<br />
                </li></ol>
            </li><li>
              按照下一节的代码示例所示设置日志记录功能。在输入日志文件中搜索“服务器 XA DLL 版本：...”这一短语。<br />
            </li></ol>
        </content></div>
      <h1 class="heading" xmlns="">配置用户定义的角色</h1><div id="sectionSection" class="section" xmlns=""><content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
          <p xmlns="">若要为特定用户授予使用 JDBC Driver 参与分布式事务的权限，请将该用户添加至 SqlJDBCXAUser 角色。例如，使用以下 Transact-SQL 代码将名为“shelby”（SQL 标准登录用户名为“shelby”）的用户添加至 SqlJDBCXAUser 角色：</p>
          <div class="sampleCode" xmlns=""><span codeLanguage="other"><pre>USE master
GO
EXEC sp_grantdbaccess 'shelby', 'shelby'
GO
EXEC sp_addrolemember [SqlJDBCXAUser], 'shelby'</pre></span></div>
          <p xmlns="">SQL 用户定义的角色是按数据库定义的。若要出于安全目的创建自己的角色，必须在每个数据库中定义角色，并在每个数据库中添加用户。主数据库中 SqlJDBCXAUser 角色的定义非常严格，因为该角色用于授予对主数据库中驻留的 SQL JDBC 扩展存储过程的访问权限。登录到主数据库后，必须先授予单个用户对主数据库的访问权限，然后再授予这些用户对 SqlJDBCXAUser 角色的访问权限。</p>
        </content></div>
    </sections></div><h1 class="heading">示例</h1><div id="sectionSection2" class="section"><content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
      <div class="sampleCode" xmlns=""><span codeLanguage="other"><pre>import java.net.Inet4Address;
import java.sql.*;
import java.util.Random;
import javax.transaction.xa.*;
import javax.sql.*;
import com.microsoft.sqlserver.jdbc.*;

public class testXA {

   public static void main(String[] args) throws Exception {

      // Create variables for the connection string.
      String prefix = "jdbc:sqlserver://";
      String serverName = "localhost";
      int portNumber = 1433;
      String databaseName = "AdventureWorks"; 
      String user = "UserName"; 
      String password = "*****";
      String connectionUrl = prefix + serverName + ":" + portNumber
         + ";databaseName=" + databaseName + ";user=" + user + ";password=" + password;

      try {
         // Establish the connection.
         Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
         Connection con = DriverManager.getConnection(connectionUrl);

         // Create a test table.
         Statement stmt = con.createStatement();
         try {
            stmt.executeUpdate("DROP TABLE XAMin"); 
         }
         catch (Exception e) {
         }
         stmt.executeUpdate("CREATE TABLE XAMin (f1 int, f2 varchar(max))");
         stmt.close();
         con.close();

         // Create the XA data source and XA ready connection.
         SQLServerXADataSource ds = new SQLServerXADataSource();
         ds.setUser(user);
         ds.setPassword(password);
         ds.setServerName(serverName);
         ds.setPortNumber(portNumber);
         ds.setDatabaseName(databaseName);
         XAConnection xaCon = ds.getXAConnection();
         con = xaCon.getConnection();

         // Get a unique Xid object for testing.
         XAResource xaRes = null;
         Xid xid = null;
         xid = XidImpl.getUniqueXid(1);

         // Cleanup.
         con.close();
         xaCon.close();

         // Open a new connection and read back the record to verify that it worked.
         con = DriverManager.getConnection(connectionUrl);
         ResultSet rs = con.createStatement().executeQuery("SELECT * FROM XAMin");
         rs.next();
         System.out.println("Read -&gt; xid = " + rs.getString(2));
         rs.close();
         con.close();
      } 

      // Handle any errors that may have occurred.
      catch (Exception e) {
         e.printStackTrace();
      }
   }
}


class XidImpl implements Xid {

   public int formatId;
   public byte[] gtrid;
   public byte[] bqual;
   public byte[] getGlobalTransactionId() {return gtrid;}
   public byte[] getBranchQualifier() {return bqual;}
   public int getFormatId() {return formatId;}

   XidImpl(int formatId, byte[] gtrid, byte[] bqual) {
      this.formatId = formatId;
      this.gtrid = gtrid;
      this.bqual = bqual;
   }

   public String toString() {
      int hexVal;
      StringBuffer sb = new StringBuffer(512);
      sb.append("formatId=" + formatId);
      sb.append(" gtrid(" + gtrid.length + ")={0x");
      for (int i=0; i&lt;gtrid.length; i++) {
         hexVal = gtrid[i]&amp;0xFF;
         if ( hexVal &lt; 0x10 )
            sb.append("0" + Integer.toHexString(gtrid[i]&amp;0xFF));
         else
            sb.append(Integer.toHexString(gtrid[i]&amp;0xFF));
         }
         sb.append("} bqual(" + bqual.length + ")={0x");
         for (int i=0; i&lt;bqual.length; i++) {
            hexVal = bqual[i]&amp;0xFF;
            if ( hexVal &lt; 0x10 )
               sb.append("0" + Integer.toHexString(bqual[i]&amp;0xFF));
            else
               sb.append(Integer.toHexString(bqual[i]&amp;0xFF));
         }
         sb.append("}");
         return sb.toString();
      }

      // Returns a globally unique transaction id.
      static byte [] localIP = null;
      static int txnUniqueID = 0;
      static Xid getUniqueXid(int tid) {

      Random rnd = new Random(System.currentTimeMillis());
      txnUniqueID++;
      int txnUID = txnUniqueID;
      int tidID = tid;
      int randID = rnd.nextInt();
      byte[] gtrid = new byte[64];
      byte[] bqual = new byte[64];
      if ( null == localIP) {
         try {
            localIP = Inet4Address.getLocalHost().getAddress();
         }
         catch ( Exception ex ) {
            localIP =  new byte[] { 0x01,0x02,0x03,0x04 };
         }
      }
      System.arraycopy(localIP,0,gtrid,0,4);
      System.arraycopy(localIP,0,bqual,0,4);

      // Bytes 4 -&gt; 7 - unique transaction id.
      // Bytes 8 -&gt;11 - thread id.
      // Bytes 12-&gt;15 - random number generated by using seed from current time in milliseconds.
      for (int i=0; i&lt;=3; i++) {
         gtrid[i+4] = (byte)(txnUID%0x100);
         bqual[i+4] = (byte)(txnUID%0x100);
         txnUID &gt;&gt;= 8;
         gtrid[i+8] = (byte)(tidID%0x100);
         bqual[i+8] = (byte)(tidID%0x100);
         tidID &gt;&gt;= 8;
         gtrid[i+12] = (byte)(randID%0x100);
         bqual[i+12] = (byte)(randID%0x100);
         randID &gt;&gt;= 8;
      }
      return new XidImpl(0x1234, gtrid, bqual);
   }
}</pre></span></div>
    </content></div><span id="seeAlsoSpan"><h1 class="heading">请参阅</h1></span><div id="seeAlsoSection" class="section" name="collapseableSection"><a href="afbb776f-05dc-4e79-bb25-2c340483e401.htm">通过 JDBC 驱动程序执行事务</a><br /><br /></div><!--[if gte IE 5]>
			<tool:tip element="seeAlsoToolTip" avoidmouse="false"/><tool:tip element="languageFilterToolTip" avoidmouse="false"/><tool:tip element="roleInfoSpan" avoidmouse="false"/>
		<![endif]-->
      <div id="footer" class="section">
        
		<hr />
		
		<span id="fb" class="feedbackcss">
			
			
		</span>
		
		<a href="9bad553b-9e70-4696-8499-2e35f772a1e0.htm">
			
			© 2010 Microsoft Corporation。保留所有权利。
		</a>
 	
	
      </div>
    </div>
  </body>
</html>